package com.randi.file.service.impl;

import com.randi.common.enums.ResultCode;
import com.randi.common.exception.ServiceException;
import com.randi.common.utils.RedisUtil;
import com.randi.common.utils.uuid.IdUtils;
import com.randi.file.entity.SysFile;
import com.randi.file.entity.vo.FileSliceMergeVo;
import com.randi.file.entity.vo.FileSliceUploadCheckVo;
import com.randi.file.entity.vo.FileSliceUploadVo;
import com.randi.file.entity.vo.FileUploadVo;
import com.randi.file.enums.FileSliceMergeStatusEnum;
import com.randi.file.service.ISysFileService;
import com.randi.file.service.ThreadFileService;
import com.randi.file.service.ISysFileUploadService;
import com.randi.file.utils.SysFileUtils;
import com.randi.file.utils.UploadFileUtils;
import com.randi.file.utils.UploadSliceUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;

/**
 * 文件上传服务实现
 *
 * @author ziye
 */
@Service
public class SysFileUploadServiceImpl implements ISysFileUploadService {

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private ThreadFileService threadFileService;

    @Resource
    private ISysFileService sysFileService;

    /**
     * 文件上传
     *
     * @param fileUpload fileUploadVo
     * @return 文件路径
     */
    @Override
    public String simpleUpload(FileUploadVo fileUpload) throws IOException {
        String fileHash = fileUpload.getFileHash();
        SysFile sysFile = sysFileService.selectSysFileByHash(fileHash);
        if (sysFile == null) {
            // 上传文件
            boolean upload = UploadFileUtils.simpleUpload(fileUpload.getFile(), fileHash);
            if (!upload) {
                return null;
            }
        }

        return UploadFileUtils.getSaveFilePath(fileHash);
    }

    /**
     * 指定路径文件上传
     *
     * @param fileUpload fileUploadVo
     * @param pathName   文件路径
     * @return 文件路径
     * @throws IOException IO异常
     */
    @Override
    public String simpleUploadByFolder(FileUploadVo fileUpload, String pathName) throws IOException {
        boolean status = UploadFileUtils.simpleUploadByFolder(fileUpload.getFile(), pathName, fileUpload.getFileHash());
        if (status) {
            UploadFileUtils.getSaveFilePath(pathName, fileUpload.getFileHash());
        }
        return null;
    }

    /**
     * 分片上传校验
     *
     * @param fileHash 文件哈希
     * @return Result
     */
    @Override
    public FileSliceUploadCheckVo sliceUploadCheck(String fileHash) {
        FileSliceUploadCheckVo sliceUpload = UploadSliceUtils.getSliceUpload(fileHash);
        if (sliceUpload.getUploadedSize().equals(BigInteger.ZERO)) {
            boolean status = sysFileService.selectSysFileByHash(fileHash) != null;
            sliceUpload.setIsExist(status);
        }
        return sliceUpload;
    }

    /**
     * 分片上传
     *
     * @param fileChunk fileChunkMergeVo
     * @return 结果
     */
    @Override
    public Boolean sliceUpload(FileSliceUploadVo fileChunk) {
        return UploadSliceUtils.uploadSlice(fileChunk);
    }

    /**
     * 分片合并
     *
     * @param sliceMerge SysFile
     * @return 任务ID
     */
    @Override
    public String sliceMerge(FileSliceMergeVo sliceMerge) {
        String taskId = IdUtils.fastSimpleUUID();
        threadFileService.handleSliceMergeTask(taskId, sliceMerge);
        return taskId;
    }

    /**
     * 分片合并校验
     *
     * @param taskId 任务ID
     * @return 校验结果
     */
    @Override
    public FileSliceMergeStatusEnum sliceMergeVerify(String taskId) {
        String statusEnum = redisUtil.getCache(taskId);
        if (statusEnum == null) {
            throw new ServiceException(ResultCode.FILE_UPLOAD_SLICE_FAIL_MERGE);
        }
        return FileSliceMergeStatusEnum.valueOf(statusEnum);
    }
}
